import { throttle } from "@/utils/index";

/**
 * 负责维护canvas实例 
 * 以及运行时变量 
 */
class Draw {
	constructor(id = 'canvas') {
		this.canvas = document.getElementById(id); //TODO: 这里做容错
		this.ctx = this.canvas.getContext("2d");
		this.hoverElement = "";  //鼠标正在某个元素上面
		this.isdruging = false;  // 是否正在拖动
		this.ArrowElement = ""; //正在画箭头
		this.elementList = []; //页面上所有的元素
		this.toolBar = { pannel: [] }; // 工具栏
		this.drugElement = ""; // 正在拖动的元素
		this.isArrowing = false; //是否正在画箭头
		// 鼠标点击事件
		this.canvas.onmousedown = this.onmousedown.bind(this);
		this.canvas.onmousemove = throttle(this.onmousemove.bind(this), 50);
	}
	/**
	 * 鼠标hover事件
	 * @param {*} e
	 */
	onmousemove(e) {
		var x = e.clientX - this.canvas.offsetLeft;
		var y = e.clientY - this.canvas.offsetTop;
		// 是否拖动某个元素
		if (this.isdruging && this.hoverElement && !this.isArrowing) {
			// 这里的x和y为相对this.canvas的坐标
			console.log(`x:${x},y: ${y}`);
			// 计算偏移后位置
			if (typeof this.hoverElement.drug === 'function') {
				this.hoverElement.x = x - this.hoverElement.offsetX;
				this.hoverElement.y = y - this.hoverElement.offsetY;
				// 计算边缘点位坐标
				this.hoverElement.drug();
			}
		} else if (this.hoverElement) {
			this.hoverElement.isCurrent = false;
		}

		// 是否为箭头
		if (this.isArrowing && this.ArrowElement) {
			console.log("【箭头】正在绘制：");
			this.ArrowElement.drug(0, 0, x, y);
			// this.ArrowElement.toX = x;
			// this.ArrowElement.toY = y;
		}
		this.hoverElement = null;

		this.reDraw(e);
	}
	/**
	 * 鼠标按下事件
	 * @param {*} e
	 */
	onmousedown(e) {
		// 是否命中某个目标元素
		if (this.hoverElement && (this.hoverElement.onmousedown || this.hoverElement.drug)) {
			this.isdruging = true;
			this.hoverElement.isCurrent = false;
			// 计算偏移量
			this.hoverElement.offsetX =
				e.clientX - this.canvas.offsetLeft - this.hoverElement.x;
			this.hoverElement.offsetY =
				e.clientY - this.canvas.offsetTop - this.hoverElement.y;
			// 执行对应的方法
			this.hoverElement.onmousedown && this.hoverElement.onmousedown();
		}

		// 点击背景, 取消工具栏的展示
		if (!this.hoverElement) {
			this.toolBar.pannel = [];
		}

		this.hoverElement = null;
		this.reDraw(e);

		document.onmouseup = this.onmouseup.bind(this);
	}
	onmouseup(e) {
		// 展示pannel :TODO: ~~~~~~~~~ ！！！！！！ ~~~~~~~~~~
		if (this.ArrowElement && (!this.hoverElement)) {
			this.toolBar.pannel = [];
			// this.drawPannel(e.clientX - this.canvas.offsetLeft, e.clientY - this.canvas.offsetTop, this.ArrowElement);
		}
		if (this.hoverElement && this.hoverElement.onmouseup) {
			this.hoverElement.onmouseup();
		}
		this.isdruging = false;
		this.drugElement = null;
		this.hoverElement = null;
		this.isArrowing = false;
		this.ArrowElement = "";
		this.reDraw(e);
	}

	reDraw = function (e) {
		var x = e.clientX - this.canvas.offsetLeft;
		var y = e.clientY - this.canvas.offsetTop;

		this.canvas.width = this.canvas.width;
		if (this.ctx) {
			// 绘制背景
			this.drawBg();
			// 显示所有的工具栏
			Object.keys(this.toolBar).forEach((tool) => {
				let tools = this.toolBar[tool];
				if (Array.isArray(tools)) {
					for (var i = 0; i < tools.length; i++) {
						var c = tools[i];
						if (!c.hide) { //不展示隐藏元素
							c.render(x, y);
						}
					}
				} else if (typeof tools === "object") {
					tools.render(x, y);
					if (!tools.hide) { //不展示隐藏元素
						tools.render(x, y);
					}
				}
			});
			// 显示所有的自定义控件
			for (var i = 0; i < this.elementList.length; i++) {
				var c = this.elementList[i];
				if (!c.hide) { //不展示隐藏元素
					c.render(x, y);
				}
			}
		}
	}

	drawBg = function () {
		const context = this.ctx;
		function drawGrid(color, stepx, stepy) {
			context.save();
			context.fillStyle = "white";
			// console.log(context);
			context.fillRect(0, 0, context.canvas.width, context.canvas.height);
			context.lineWidth = 0.5;
			context.strokeStyle = color;
			for (var i = 0; i <= context.canvas.width; i += stepx) {
				context.beginPath();
				context.moveTo(i, 0);
				context.lineTo(i, context.canvas.height);
				context.closePath();
				context.stroke();
			}
			for (var j = 0; j <= context.canvas.height; j += stepy) {
				context.beginPath();
				context.moveTo(0, j);
				context.lineTo(context.canvas.width, j);
				context.closePath();
				context.stroke();
			}
			context.restore();
		}
		drawGrid("#ccc", 20, 20);
	}
}

let drawInstance = null;
const getInstance = () => {
	if (!drawInstance) {
		drawInstance = new Draw('canvas')
	}
	return drawInstance
}
export default getInstance;